import uuid
from io import BytesIO
import pandas as pd
import pytz

import tornado.web
import tornado.httpclient
import json

from tair import Tair

import settings
import traceback
from common.log import logger
from db.es.es_service import ElasticsearchStorage
from datetime import datetime, timedelta, timezone, date, time
from util_tool.conversation_util import ConversationUtil
from bot.enterprise_wechat_gpt.util.transfer_util import *
from bot.enterprise_wechat_gpt.config.conf import *

tair_util = TairUtil()
es = ElasticsearchStorage()


class ChatRecordRpa:
    def __init__(self, customerId, cusWechatName, agentName, msgContent, msgType, msgTime, msgSend, msgReceive,
                 userWechatId, agentWechatId):
        self.customerId = customerId  # 客户id
        self.userWechatId = userWechatId  # 客户微信id
        self.cusWechatName = cusWechatName  # 客户微信昵称
        self.agentWechatId = agentWechatId  # 坐席微信id
        self.agentName = agentName  # 坐席微信昵称
        self.msgContent = msgContent  # 消息内容
        self.msgType = msgType  # 消息类型
        self.msgTime = msgTime  # 消息时间
        self.msgSend = msgSend  # 消息发送方
        self.msgReceive = msgReceive  # 消息接收方

    def to_json(self):
        return json.dumps(self, ensure_ascii=False, default=lambda o: o.__dict__)

    @staticmethod
    def from_json(json_str):
        data = json.loads(json_str)
        customerId = data.get("customerId")
        cusWechatName = data.get("cusWechatName")
        agentName = data.get("agentName")
        msgContent = data.get("msgContent")
        msgType = data.get("msgType")
        msgTime = data.get("msgTime")
        msgSend = data.get("msgSend")
        msgReceive = data.get("msgReceive")
        userWechatId = data.get("userWechatId")
        agentWechatId = data.get("agentWechatId")

        return ChatRecordRpa(customerId, cusWechatName, agentName, msgContent, msgType, msgTime, msgSend, msgReceive,
                             userWechatId, agentWechatId)


class ChatRecord:

    def __init__(self, customer_id, session_id, role, message_id, msg_type, attitude, text_info, message_time,
                 userWechatId):
        self.customer_id = customer_id
        self.session_id = session_id
        self.role = role
        self.message_id = message_id
        self.msg_type = msg_type
        self.attitude = attitude
        self.text_info = text_info
        self.message_time = message_time
        self.userWechatId = userWechatId

    def to_json(self):
        return json.dumps(self, ensure_ascii=False, default=lambda o: o.__dict__)

    @staticmethod
    def from_json(json_str):
        data = json.loads(json_str)
        customer_id = data.get("customer_id")
        session_id = data.get("session_id")
        role = data.get("role")
        message_id = data.get("message_id")
        msg_type = data.get("msg_type")
        attitude = data.get("attitude")
        text_info = data.get("text_info")
        message_time = data.get("message_time")
        userWechatId = data.get("userWechatId")

        return ChatRecord(customer_id, session_id, role, message_id, msg_type, attitude, text_info, message_time,
                          userWechatId)


class ConversationStoreHandler(tornado.web.RequestHandler):

    def post(self):
        try:
            conversationUtil = ConversationUtil()
            records = json.loads(self.request.body)
            logging.info(f"对话存储保存数据: {records}")

            if records:
                record = records[0]
                transfer_tag = get_transfer_tag_from_tair(
                    record.get('agentWechatId', '') + ":" + record.get('customerId', ''))

                conversations = build_conversation(transfer_tag, records)

                conversationUtil.store_qw_conversation_new(conversations)
            self.write({"code": 200, "msg": "对话存储成功"})
        except:
            logger.error(traceback.format_exc())
            self.write({"code": 500, "msg": "对话存储失败"})


class ConversationInfoDownloadHandler(tornado.web.RequestHandler):

    def get(self):
        start_date = self.get_argument('start_date', '')
        end_date = self.get_argument('end_date', '')
        data = []
        try:
            session_ids = set([])
            if not start_date:
                start_date = datetime.now().strftime('%Y-%m-%d')
            if not end_date:
                end_date = (datetime.now() + timedelta(days=1)).strftime('%Y-%m-%d')
            # 定义查询条件

            date_range_query = {
                "range": {
                    "message_time": {
                        "gte": start_date,
                        "lte": end_date
                    }
                }
            }
            session_query = {
                "query": {
                    "bool": {
                        "must": [date_range_query]
                    }
                }, "sort": [
                    {
                        "session_id": {
                            "order": "asc"
                        }
                    },
                    {
                        "message_time": {
                            "order": "asc"
                        }
                    }
                ],
                "size": 10000
            }

            # 执行查询
            results = es.search_documents(settings.QW_CONVERSATION_INDEX, session_query)
            df = pd.DataFrame(columns=["客户id", "对话id", "角色", "对话内容", "对话时间", "消息类型", "态度"])
            if results:
                for hit in results:
                    session_id = hit["_source"].get("session_id", None)
                    role = hit["_source"].get("role", None)
                    text_info = hit["_source"].get("text_info", None)
                    message_time = hit["_source"]["message_time"]
                    msg_type = hit["_source"]["msg_type"]
                    customer_id = hit["_source"].get("customer_id", None)

                    df = df.append(
                        {"客户id": customer_id, "对话id": session_id, "角色": role, "对话内容": text_info,
                         "对话时间": message_time, "消息类型": msg_type
                         },
                        ignore_index=True)
                    session_ids.add(session_id)

                def add_empty_row(group):
                    return pd.concat([group, pd.DataFrame([[''] * len(group.columns)], columns=group.columns)],
                                     ignore_index=True)

                df = df.groupby('对话id').apply(add_empty_row).reset_index(drop=True)
                excel_io = BytesIO()
                df.to_excel(excel_io, index=False)
                # 将BytesIO的内容发送给客户端作为附件下载
                excel_io.seek(0)  # 将指针回到文件开头，确保从头开始读取

                # 导出到Excel文件
                file_name = f"conversation_{start_date}.xlsx"

                self.set_header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                self.set_header("Content-Disposition", "attachment; filename=" + file_name)
                # 将 BytesIO 内容发送给客户端
                self.write(excel_io.getvalue())
            else:
                self.write(json.dumps(data))
        except Exception:
            logger.error(traceback.format_exc())
            self.write(json.dumps(data))


def get_transfer_tag_from_tair(user_tag):
    """
        从Tair中获取转人标记 取昨天最后一个标识和今天的全部标识
    """
    conversation_list = tair_util.lrange(TairUtil.history_key + user_tag, 0, -1)

    today_midnight_timestamp = get_today_midnight_timestamp()

    # 使用lambda函数过滤掉系统消息（system:人工），并仅保留系统消息（system:系统）
    filtered_system_messages = list(filter(lambda x: "系统" in x, conversation_list))

    dict_conversation_list = [json.loads(message) for message in filtered_system_messages]

    # 初始化新的集合
    new_collection = []

    # 遍历过滤后的系统消息，将今天之前的消息添加到新集合
    for message in dict_conversation_list:
        msg_timestamp = message["msgtime"]

        if msg_timestamp >= today_midnight_timestamp:
            new_collection.append(message)
        else:
            new_collection.append(message)
            break  # 遇到未来的消息后终止循环

    sorted_new_conversation_list = sorted(new_collection, key=lambda x: x["msgtime"], reverse=False)

    return sorted_new_conversation_list


def get_today_midnight_timestamp():
    """
    获取今天凌晨的时间戳
    """
    # 获取当前时间
    current_datetime = datetime.now()

    # 获取今天凌晨的时间
    today_midnight = current_datetime.replace(hour=0, minute=0, second=0, microsecond=0)

    # 转换为 UTC 时间
    today_midnight_utc = today_midnight.astimezone(timezone.utc)

    # 转换为 UNIX 时间戳
    today_midnight_timestamp = today_midnight_utc.timestamp()

    return today_midnight_timestamp


def build_conversation(transfer_tag, records):
    """
    根据转人标记和甲方的对话记录重新构建对话
    Args:
        transfer_tag: 转人标记
        records: 甲方对话记录
    """
    conversations = list()

    for record in records:

        # 默认都是助手发的
        record['role'] = 'assistant'

        msg_time = record.get('msgTime', None)

        msg_content = record.get('msgContent', '{}')

        msg_content_json = json.loads(msg_content)

        date_obj = datetime.strptime(msg_time, "%Y-%m-%d %H:%M:%S")

        # 转换为时间戳（秒级）
        msg_timestamp = int(date_obj.timestamp())
        role = None

        if record['msgSend'] == record['userWechatId']:
            record['role'] = 'user'

            conversation = ChatRecord(record.get('customerId'),
                                      record.get('agentWechatId', '') + ":" + record.get('customerId', ''),
                                      record.get('role', 'assistant'),
                                      record.get('billId', str(uuid.uuid4()).replace('-', '')),
                                      record.get('msgType', 'text'), 'no', msg_content_json.get('content'),
                                      datetime.fromtimestamp(msg_timestamp).strftime('%Y-%m-%dT%H:%M:%S'),
                                      record.get('userWechatId', ''))

            conversations.append(conversation.to_json())
            continue

        for i, tag in enumerate(transfer_tag):
            if i == 0:
                if tag['msgtime'] > msg_timestamp:
                    if tag['transfer'] is False:
                        role = 'agent'
                    elif tag['transfer'] is True:
                        role = 'assistant'
            if tag['msgtime'] <= msg_timestamp:
                if tag['transfer'] is False:
                    role = 'assistant'
                elif tag['transfer'] is True:
                    role = 'agent'

        if role:
            record['role'] = role

        conversation = ChatRecord(record.get('customerId'),
                                  record.get('agentWechatId', '') + ":" + record.get('customerId', ''),
                                  record.get('role', 'assistant'),
                                  record.get('billId', str(uuid.uuid4()).replace('-', '')),
                                  record.get('msgType', 'text'), 'no', msg_content_json.get('content'),
                                  datetime.fromtimestamp(msg_timestamp).strftime('%Y-%m-%dT%H:%M:%S'),
                                  record.get('userWechatId', ''))

        conversations.append(conversation.to_json())

    return conversations

# if __name__ == '__main__':

# tair: Tair = Tair(
#     host="r-8vbc4cl7wj4g03lum6pd.redis.zhangbei.rds.aliyuncs.com",
#     # host=profile_['redis']['host'],
#     port=6379,
#     db=0,
#     username="lingxi",
#     password="Lingxi123#",
#     decode_responses=True
# )
# conversation_list = tair.lrange(TairUtil.history_key + "JDJT_743124:K619670195365016474174", 0, -1)
#
# today_midnight_timestamp = get_today_midnight_timestamp()
#
# # 使用lambda函数过滤掉系统消息（system:人工），并仅保留系统消息（system:系统）
# filtered_system_messages = list(filter(lambda x: "系统" in x, conversation_list))
#
# dict_conversation_list = [json.loads(message) for message in filtered_system_messages]
#
# # 初始化新的集合
# new_collection = []
#
# # 遍历过滤后的系统消息，将今天之前的消息添加到新集合
# for message in dict_conversation_list:
#     msg_timestamp = message["msgtime"]
#
#     if msg_timestamp >= today_midnight_timestamp:
#         new_collection.append(message)
#     else:
#         new_collection.append(message)
#         break  # 遇到未来的消息后终止循环
#
# sorted_new_conversation_list = sorted(new_collection, key=lambda x: x["msgtime"], reverse=False)
# print(sorted_new_conversation_list)
